export default {
  name: 'PickerCol',
  props: {
    items: { type: Array, default: () => { return [] } },
    value: [Number, String],
    temp: Number,//缓存上一次位置
  },
  data() {
    return {
      offset: 0, // 列表初始化时的偏移量（列表初始化时，选项是聚焦在中间的，通过offset强制往上挪3项，以达到初始选项是为顶部的那项）
      rowHeight: (68 / 7.5) * (window.innerWidth / 100), // 列表每一行的高度, 这里胡单位是按 750的设计尺寸,实际高度为68px,如果有vw为单位所以要进行换算
      bodyHeight: (576 / 7.5) * (window.innerWidth / 100), //picker的高度，用于辅助点击滚动的计算
      startY: '',  // 保存开始按下的位置
      endY: '', // 保存结束时的位置
      startTime: '',// 开始触摸的时间
      translate: '',// 缓存 translate
      points: [],// 记录移动点,
      diff: '',
      time: '' //动画时间
    }
  },
  watch: {
    value(v) {
      this.scroll()
    }
  },
  mounted() {
    //在安卓里面，拿到的是0 ，所以延迟
    setTimeout(() => {
      this.rowHeight = (68 / 7.5) * (window.innerWidth / 100) // 列表每一行的高度, 这里胡单位是按 750的设计尺寸,实际高度为68px,如果有vw为单位所以要进行换算
      this.bodyHeight = (576 / 7.5) * (window.innerWidth / 100) //picker的高度，用于辅助点击滚动的计算
      this.scroll()
    }, 500);
  },
  methods: {
    scroll() {
      let { temp, items = [], offset, rowHeight, value } = this
      // 首次触发选中事件
      // 如果有缓存的选项，则用缓存的选项，否则使用中间值。
      const current = this.getIndex(value)
      if (current != null || (temp !== null && temp < items.length)) {
        const index = current != null ? current : temp;
        // defaults.onChange.call(this, items[index], index);
        this.$emit('change', items[index], index)
        this.translate = (offset - index) * rowHeight;
        // console.log('temp', temp)
      } else {
        const index = this.getDefaultIndex(items);
        // defaults.onChange.call(this, items[index], index);
        this.$emit('change', items[index], index)
        this.translate = this.getDefaultTranslate(offset, rowHeight, items);
      }
      this.diff = this.translate

      // setTranslate($scrollable, translate);
    },
    getIndex(key) {
      let current = null
      let { items = [] } = this
      if (key===null || key === undefined || !items.length) return current;
      for (let i = 0; i < items.length; i++) {
        let value = typeof items[i] == 'object' ? items[i].value : items
        if (value == key) {
          current = i
          return i
        }
      }
      return current;
    },
    getDefaultTranslate(offset, rowHeight, items) {
      const currentIndex = this.getDefaultIndex(items);
      return (offset - currentIndex) * rowHeight;
    },
    getDefaultIndex(items) {
      let current = Math.floor(items.length / 2);
      let count = 0;
      while (!!items[current] && items[current].disabled) {
        current = ++current % items.length;
        count++;

        if (count > items.length) {
          throw new Error('No selectable item.');
        }
      }

      return current;
    },
    // getMax(offset, rowHeight) {
    //   return offset * rowHeight;
    // },
    // getMin(offset, rowHeight, length) {
    //   return -(rowHeight * (length - offset - 1));
    // },
    // setTransition($target, time) {
    //   return $target.css({
    //     '-webkit-transition': `all ${time}s`,
    //     'transition': `all ${time}s`
    //   });
    // },
    // setTranslate($target, diff) {
    //   return $target.css({
    //     '-webkit-transform': `translate3d(0, ${diff}px, 0)`,
    //     'transform': `translate3d(0, ${diff}px, 0)`
    //   });
    // },
    stop(diff) {
      let { rowHeight, offset, translate, items } = this
      // console.log(items.length, translate, diff)
      translate += diff;
      // 移动到最接近的那一行
      translate = Math.round(translate / rowHeight) * rowHeight;
      const max = 0//this.getMax(offset, rowHeight);
      const min = - rowHeight * (items.length - 1)// this.getMin(offset, rowHeight, items.length)
      // 不要超过最大值或者最小值
      if (translate > max) {
        translate = max;
      }
      if (translate < min) {
        translate = min;
      }

      // 如果是 disabled 的就跳过
      let index = (offset - Math.round(translate / rowHeight)); //这里计算的可能是小数
      while (!!items[index] && items[index].disabled) {
        diff > 0 ? ++index : --index;
      }
      translate = (offset - index) * rowHeight;
      // translate = Math.min(0, translate) //最小值为0
      // translate = Math.max(offset * rowHeight, translate)
      this.translate = translate
      // setTransition($scrollable, .3);
      this.time = .3
      this.diff = translate
      // setTranslate($scrollable, translate);
      let item = this.items[index]
      let value = typeof item == 'object' ? item.value : item
      if (this.value !== value) {
        this.$emit('input', value)
        // 触发选择事件
        this.$emit('change', item, index)
        // defaults.onChange.call(this, defaults.items[index], index);
      }
    },
    start(pageY) {
      this.startY = pageY;
      this.startTime = +new Date();
    },
    move(pageY) {
      this.endY = pageY;
      const diff = this.endY - this.startY;

      // setTransition($scrollable, 0);
      this.time = 0
      this.diff = this.translate + diff
      // setTranslate($scrollable, (this.translate + diff));
      this.startTime = +new Date();
      this.points.push({ time: this.startTime, y: this.endY });
      if (this.points.length > 40) {
        this.points.shift();
      }
    },
    end(pageY) {
      if (!this.startY) return;

      /**
       * 思路:
       * 0. touchstart 记录按下的点和时间
       * 1. touchmove 移动时记录前 40个经过的点和时间
       * 2. touchend 松开手时, 记录该点和时间. 如果松开手时的时间, 距离上一次 move时的时间超过 100ms, 那么认为停止了, 不执行惯性滑动
       *    如果间隔时间在 100ms 内, 查找 100ms 内最近的那个点, 和松开手时的那个点, 计算距离和时间差, 算出速度
       *    速度乘以惯性滑动的时间, 例如 300ms, 计算出应该滑动的距离
       */
      const endTime = new Date().getTime();
      const relativeY = this.$refs.picker.getBoundingClientRect().top + this.bodyHeight / 2;
      this.endY = pageY;

      // 如果上次时间距离松开手的时间超过 100ms, 则停止了, 没有惯性滑动
      let { endY, startY, points, startTime } = this
      // debugger;
      if (endTime - startTime > 100) {
        //如果end和start相差小于10，则视为
        if (Math.abs(endY - startY) > 10) {
          this.stop(endY - startY);
        } else {
          this.stop(relativeY - endY);
        }
      } else {
        if (Math.abs(endY - startY) > 10) {
          const endPos = points.length - 1;
          let startPos = endPos;
          for (let i = endPos; i > 0 && startTime - points[i].time < 100; i--) {
            startPos = i;
          }

          if (startPos !== endPos) {
            const ep = points[endPos];
            const sp = points[startPos];
            const t = ep.time - sp.time;
            const s = ep.y - sp.y;
            const v = s / t; // 出手时的速度
            const diff = v * 150 + (endY - startY); // 滑行 150ms,这里直接影响“灵敏度”
            this.stop(diff);
          }
          else {
            this.stop(0);
          }
        } else {
          this.stop(relativeY - endY);
        }
      }

      this.startY = null;
    }
  },
  render() { //k-picker-col-item
    const items = (this.items || []).map((item) => {
      return <div class={'k-picker-col-item' + (item.disabled ? ' k-picker-col-item-disabled' : '')}>{typeof item == 'object' ? item.label : item}</div>;
    })
    let props = {
      ref: 'picker',
      class: 'k-picker-col',
      on: {
        touchstart: e => this.start(e.changedTouches[0].clientY),
        touchmove: e => { this.move(e.changedTouches[0].clientY); e.preventDefault() },
        touchend: e => {
          // console.log(e);
          this.end(e.changedTouches[0].clientY)
        },
      }
    }
    // 判断是否支持touch事件 https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
    const isSupportTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch;
    if (!isSupportTouch) {
      props.on.mousedown = e => {
        this.start(e.clientY);
        e.stopPropagation();
        e.preventDefault();
      }
      props.on.mousemove = e => {
        if (!this.startY) return;
        this.move(e.clientY);
        e.stopPropagation();
        e.preventDefault();
      }
      props.on.mouseleave = e => {
        this.end(e.clientY);
        e.stopPropagation();
        e.preventDefault();
      }
      props.on.mouseup = e => {
        this.end(e.clientY);
        e.stopPropagation();
        e.preventDefault();
      }
    }
    let { diff, time } = this
    const contentPros = {
      class: 'k-picker-col-content',
      style: {
        '-webkit-transform': `translate3d(0, ${diff}px, 0)`,
        'transform': `translate3d(0, ${diff}px, 0)`,
        '-webkit-transition': `all ${time}s`,
        'transition': `all ${time}s`
      }
    }
    return (
      <div {...props}>
        <div class="k-picker-col-mask"></div>
        <div class="k-picker-col-indicator"></div>
        <div {...contentPros}>
          {items}
        </div>
      </div>
    )
  }
}